module render.renderer_a2;

import utils.vector2;
import utils.color;
import render.abstractrenderer;
import std.math;

enum A2Function {
    sine,
    campbellRobson,
    aliasTestCircle,
    aliasTestLines,
    krois
}

const float C2PI16 = 2*PI*16;
const float C604PI = 60*4*PI;
const float C2PI = 2*PI;

float fSimpleSine(Vector2f pos) {
    return 0.5f*(1+sin(C2PI16*pos.x*pos.x));
}

float fCampbellRobson(Vector2f pos) {
    return 0.5f*(1+pow(cast(real)(1-pos.y),3)*sin(C2PI*pos.x*exp(5*pos.x)));
}

float fAliasTestCircle(Vector2f pos) {
    return 0.5f*(1+sin(1600*(pos.x*pos.x+pos.y*pos.y)));
}

float fAliasTestLines(Vector2f pos) {
    return 0.5f*(1+sin(C604PI*atan(pos.y/pos.x)));
}

float fKrois(Vector2f pos) {
    float a = pos.x-0.5f;
    float b = pos.y-0.5f;
    return sqrt(a*a+b*b);
}

float positive(float x) {
    return x>0.5f?1.0f:0.0f;
}

class Renderer_A2: AbstractRenderer {
    bool mDoTresholdFunc = false;
    A2Function mCurFuncId;
    float function(Vector2f) mF = &fSimpleSine;

    public void initRender(Vector2f pixelSize, Vector2f validFrom,
        Vector2f validTo)
    {
        //nop
    }

    public RGBColor render(Vector2f pos) {
        RGBColor ret;

        float val = mF(pos);

        if (mDoTresholdFunc)
            val = positive(val);

        ret.r = ret.b = ret.g = val;
        return ret;
    }

    public bool doTresholdFunc() {
        return mDoTresholdFunc;
    }

    public void doTresholdFunc(bool val) {
        mDoTresholdFunc = val;
    }

    public void func(A2Function func) {
        mCurFuncId = func;
        switch (func) {
            case A2Function.sine:
                mF = &fSimpleSine;
                break;
            case A2Function.campbellRobson:
                mF = &fCampbellRobson;
                break;
            case A2Function.aliasTestCircle:
                mF = &fAliasTestCircle;
                break;
            case A2Function.aliasTestLines:
                mF = &fAliasTestLines;
                break;
            case A2Function.krois:
                mF = &fKrois;
                break;
        }
    }
    public A2Function func() {
        return mCurFuncId;
    }
}
